             package com.java.diagnostics.visualizer.gc.solarissupport.parser;
             
             import com.java.diagnostics.visualizer.data.DataLevel;
             import com.java.diagnostics.visualizer.data.SourceData;
             import com.java.diagnostics.visualizer.data.UnstructuredData;
             import com.java.diagnostics.visualizer.exceptions.GCAndMemoryVisualizerException;
             import com.java.diagnostics.visualizer.factory.DataFactory;
             import com.java.diagnostics.visualizer.factory.SourceDataFactory;
             import com.java.diagnostics.visualizer.gc.solarissupport.util.Messages;
             import com.java.diagnostics.visualizer.impl.factory.LogFactory;
             import com.java.diagnostics.visualizer.parser.vgc.VGCDataManager;
             import com.java.diagnostics.visualizer.parser.vgc.VGCPlainTextParser;
             import com.java.diagnostics.visualizer.parser.vgc.constants.VGCGCScopes;
             import com.java.diagnostics.visualizer.parser.vgc.j926.J926DateConverter;
             import com.java.diagnostics.visualizer.properties.OutputProperties;
             import com.java.diagnostics.visualizer.sources.Source;
             import java.io.BufferedReader;
             import java.io.IOException;
             import java.util.logging.Level;
             import java.util.logging.Logger;
             import java.util.regex.Matcher;
             import java.util.regex.Pattern;
             
             public class InstanceOracleG1VGCParser
               extends VGCPlainTextParser
             {
               private static final String GC_PAUSE = "GC pause";
               private static final String FULL_GC = "Full GC";
               private static final String EDEN = "Eden";
               private static final String SURVIVORS = "Survivors";
               private static final String HEAP = "Heap";
               private static final String CONCURRENT = "concurrent";
               private static final String CONC_MARK_END = "concurrent-mark-end";
               private static final String CONC_COUNT_END = "concurrent-count-end";
               private static final String CONC_CLEANUP_END = "concurrent-cleanup-end";
               private static final double BYTES_PER_KB = 1024.0D;
               private static final double BYTES_PER_MB = 1048576.0D;
               private static final Pattern CONCURRENT_TIME = Pattern.compile("(\\,\\s)([0-9]*[\\.][0-9]*)");
               
               private static final Pattern HEAP_ELEMENT = Pattern.compile("([0-9][0-9]*[BKM])\\(([0-9][0-9]*[BKM])\\)->([0-9][0-9]*[BKM])\\(([0-9][0-9]*[BKM])\\)");
               
               private static final Pattern HEAP_SIZE_ELEMENT = Pattern.compile("([0-9][0-9]*[BKM])->([0-9][0-9]*[BKM])");
               
               private static final Logger TRACE = LogFactory.getTrace(InstanceOracleG1VGCParser.class);
               
               private static final DataFactory factory = DataFactory.getFactory("VGC");
               
               private static final Pattern TIMESTAMP_EXPRESSION = Pattern.compile("([0-9]*[\\.,][0-9][0-9][0-9]): \\[([A-z\\-]*)");
               
               private static final Pattern DATESTAMP_EXPRESSION = Pattern.compile("([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9])");
               
               private static final Pattern PAUSE_EXPRESSION = Pattern.compile(", ([0-9]*[\\.,][0-9]*) secs\\]");
               
               private static final String VERSION = Messages.getString("SunVGCParser.sun.version");
               
               private double lastTimestamp = -1.0D;
               private double restartTimestamp = 0.0D;
               
               public SourceData parse(Source source, OutputProperties properties)
                 throws GCAndMemoryVisualizerException
               {
                 TRACE.entering(this.className, "parse");
                 String line = null;
                 try
                 {
                   String variantIdentifier = source.getVariantIdentifier();
                   this.sourceData = 
                     SOURCE_DATA_FACTORY.createSourceData(variantIdentifier);
                   this.dataManager = new OracleDataManager(source, this.sourceData, properties);
                   
                   BufferedReader reader = source.getSafeBufferedStreamReader();
                   line = reader.readLine();
                   
                   while (line != null) {
                     handleLine(line, reader, properties);
                     line = reader.readLine();
                   }
                   String version = Messages.getString("SunVGCParser.sun.version");
                   UnstructuredData versionData = factory.createUnstructuredData(
                     "VGCLabels.version", Messages.getString("VGCLabels.version"), 
                     version);
                   addData(versionData);
                   writeOutSourceData();
                   this.dataManager.complete();
                   reader.close();
                 } catch (IOException e) {
                   TRACE.warning(line);
                   e.printStackTrace();
                   TRACE.log(Level.WARNING, 
                     Messages.getString("SunVGCParser.caught.exception"), e);
                   this.sourceData = null;
                 }
                 TRACE.exiting(this.className, "parse");
                 return this.sourceData;
               }
               
               private void handleLine(String line, BufferedReader reader, OutputProperties properties)
                 throws GCAndMemoryVisualizerException
               {
                 handleTimestamp(line, properties);
                 
                 if ((line.contains("GC pause")) || (line.contains("Full GC"))) {
                   extractGCType(line);
                 } else if (line.contains("Eden")) {
                   handleHeapElements(line);
                 } else if (line.contains("concurrent")) {
                   handleConcurrentElements(line);
                 }
               }
               
               private void handleConcurrentElements(String line) {
                 if (line.contains("concurrent-mark-end")) {
                   Matcher expression = CONCURRENT_TIME.matcher(line);
                   boolean hasMarkTime = expression.find();
                   if (hasMarkTime) {
                     String stamp = expression.group(2);
                     double timestamp = Double.parseDouble(stamp) * 1000.0D;
                     addDataPoint("VGCLabels.mark.times", timestamp);
                     
                     addDataPoint("OracleVGCLabels.stop.the.world.pause", timestamp);
                   }
                 } else if (line.contains("concurrent-count-end")) {
                   Matcher expression = CONCURRENT_TIME.matcher(line);
                   boolean hasCountTime = expression.find();
                   if (hasCountTime) {
                     String stamp = expression.group(2);
                     double timestamp = Double.parseDouble(stamp) * 1000.0D;
                     addDataPoint("OracleVGCLabels.count.time", timestamp);
                     
                     addDataPoint("OracleVGCLabels.stop.the.world.pause", timestamp);
                   }
                 } else if (line.contains("concurrent-cleanup-end")) {
                   Matcher expression = CONCURRENT_TIME.matcher(line);
                   boolean hasCleanupTime = expression.find();
                   if (hasCleanupTime) {
                     String stamp = expression.group(2);
                     double timestamp = Double.parseDouble(stamp) * 1000.0D;
                     addDataPoint("OracleVGCLabels.cleanup.time", timestamp);
                     
                     addDataPoint("OracleVGCLabels.stop.the.world.pause", timestamp);
                   }
                 }
               }
               
               private void extractGCType(String line) {
                 if (line.contains("partial")) {
                   addDataPoint("VGCLabels.gc.scopes", VGCGCScopes.G1_PARTIAL_INT);
                 } else if (line.contains("young")) {
                   addDataPoint("VGCLabels.gc.scopes", VGCGCScopes.YOUNG_INT);
                 } else if (line.contains("Full GC")) {
                   addDataPoint("VGCLabels.gc.scopes", VGCGCScopes.FULL_GC_INT);
                 }
                 Matcher expression = PAUSE_EXPRESSION.matcher(line);
                 boolean hasPause = expression.find();
                 if (hasPause) {
                   String pauseString = expression.group(1);
                   pauseString = pauseString.replace(',', '.');
                   double pauseTime = Double.parseDouble(pauseString) * 1000.0D;
                   addDataPoint("VGCLabels.pause.times.without.exclusive.access", 
                     pauseTime);
                   
                   addDataPoint("OracleVGCLabels.stop.the.world.pause", pauseTime);
                 }
               }
               
               private void handleTimestamp(String line, OutputProperties properties) {
                 double timestamp = extractDatestamp(line);
                 if (timestamp > 0.0D) {
                   this.dataManager.createXAxis(true);
                 } else {
                   timestamp = extractTimestamp(line);
                   if (timestamp > 0.0D) {
                     this.dataManager.createXAxis(false);
                     if (timestamp < this.lastTimestamp) {
                       logRestart();
                       this.restartTimestamp = this.lastTimestamp;
                       this.lastTimestamp = timestamp;
                     }
                   }
                 }
                 
                 if (timestamp > 0.0D)
                 {
                   this.dataManager.setX(timestamp + this.restartTimestamp);
                   this.lastTimestamp = timestamp;
                 }
               }
               
               private double extractDatestamp(String line) {
                 Matcher expression = DATESTAMP_EXPRESSION.matcher(line);
                 boolean hasDatestamp = expression.find();
                 double timestamp = -1.0D;
                 if (hasDatestamp) {
                   String stamp = expression.group(1);
                   timestamp = J926DateConverter.parseDate(stamp);
                 }
                 return timestamp;
               }
               
               private double extractTimestamp(String line) {
                 Matcher expression = TIMESTAMP_EXPRESSION.matcher(line);
                 boolean hasTimestamp = expression.find();
                 double timestamp = -1.0D;
                 if (hasTimestamp) {
                   String stamp = expression.group(1);
                   timestamp = Double.parseDouble(stamp) * 1000.0D;
                 }
                 return timestamp;
               }
               
               private void handleHeapElements(String line) {
                 String partLine = null;
                 int found = -1;
                 createEdenDataPoints(line);
                 found = line.indexOf("Survivors");
                 if (found > 0) {
                   partLine = line.substring(found);
                   createSurvivorDataPoints(partLine);
                   found = partLine.indexOf("Heap");
                   if (found > 0) {
                     partLine = partLine.substring(found);
                     createHeapDataPoints(partLine);
                   }
                 }
               }
               
               private void createEdenDataPoints(String line) {
                 Matcher heapMatcher = HEAP_ELEMENT.matcher(line);
                 boolean hasEdenSizes = heapMatcher.find();
                 if (hasEdenSizes) {
                   String usedEdenBefore = heapMatcher.group(1);
                   String edenSizeBefore = heapMatcher.group(2);
                   String usedEdenAfter = heapMatcher.group(3);
                   
                   addDataPoint("OracleVGCLabels.used.eden.before", 
                     calculateHeapValueInBytes(usedEdenBefore), this.currentComment);
                   addDataPoint("OracleVGCLabels.eden.size.before", 
                     calculateHeapValueInBytes(edenSizeBefore), this.currentComment);
                   addDataPoint("OracleVGCLabels.used.eden.after", 
                     calculateHeapValueInBytes(usedEdenAfter), this.currentComment);
                 }
               }
               
               private void createSurvivorDataPoints(String line)
               {
                 Matcher heapMatcher = HEAP_SIZE_ELEMENT.matcher(line);
                 boolean hasSurvivorSizes = heapMatcher.find();
                 if (hasSurvivorSizes) {
                   String survivorSizeBefore = heapMatcher.group(1);
                   String survivorSizeAfter = heapMatcher.group(2);
                   addDataPoint("OracleVGCLabels.used.survivor.before", 
                     calculateHeapValueInBytes(survivorSizeBefore), 
                     this.currentComment);
                   addDataPoint("OracleVGCLabels.used.survivor.after", 
                     calculateHeapValueInBytes(survivorSizeAfter), 
                     this.currentComment);
                 }
               }
               
               private void createHeapDataPoints(String line) {
                 Matcher heapMatcher = HEAP_ELEMENT.matcher(line);
                 heapMatcher.find();
                 
                 String usedHeapBefore = heapMatcher.group(1);
                 String heapSizeBefore = heapMatcher.group(2);
                 String usedHeapAfter = heapMatcher.group(3);
                 String heapSizeAfter = heapMatcher.group(4);
                 addDataPoint("OracleVGCLabels.used.heap.before", 
                   calculateHeapValueInBytes(usedHeapBefore), this.currentComment);
                 addDataPoint("OracleVGCLabels.heap.size.before", 
                   calculateHeapValueInBytes(heapSizeBefore), this.currentComment);
                 addDataPoint("OracleVGCLabels.used.heap.after", 
                   calculateHeapValueInBytes(usedHeapAfter), this.currentComment);
                 addDataPoint("OracleVGCLabels.heap.size.after", 
                   calculateHeapValueInBytes(heapSizeAfter), this.currentComment);
               }
               
               private double calculateHeapValueInBytes(String heapString) {
                 double beforeValue = 0.0D;
                 String valueString = heapString.substring(0, heapString.length() - 1);
                 if (heapString.endsWith("K")) {
                   beforeValue = Double.parseDouble(valueString) * 1024.0D;
                 } else if (heapString.endsWith("M")) {
                   beforeValue = Double.parseDouble(valueString) * 1048576.0D;
                 } else if (heapString.endsWith("B")) {
                   beforeValue = Double.parseDouble(valueString);
                 }
                 return beforeValue;
               }
               
               protected void addVersion() {
                 UnstructuredData versionData = factory.createUnstructuredData(
                   "VGCLabels.version", Messages.getString("VGCLabels.version"), 
                   VERSION);
                 this.sourceData.addData(versionData, DataLevel.VARIANT);
               }
               
               protected boolean isTimeStampRelative()
               {
                 return false;
               }
             }


